com! VimessengerSignOff py signOff()
map <Leader>b :call VimessengerShowBuddyList()<CR>

set switchbuf=usetab
let g:rosterFile = '/tmp/vimessengerRoster'

"Internal (don't talk to the server)
"{{{ VimessengerShowBuddyList
function! VimessengerShowBuddyList()
    exe "bad " . g:rosterFile
    try
        exe "sbuffer" . g:rosterFile
    catch
        exe "tabe " . g:rosterFile
    endtry

    set nowrap

    nnoremap <buffer> <silent> <Return> :py vimessengerBeginChat()<CR>
endfunction
"}}}

python <<EOF
import vim
chats = {}
chatServer = ""

import sys,os,xmpp,time,select,socket,asyncore,base64,threading

#{{{ class VimJabber
class VimJabber(threading.Thread):
    #Vim Executable to use
    _vim = 'vim'
    _rosterFile = '/tmp/vimessengerRoster'
    _roster = {}

    #{{{ __init__
    def __init__(self, jid, password, callbacks):
        self._jid = jid
        self._password = password
        self._recievedMessage = callbacks
        threading.Thread.__init__ ( self )
    #}}}
    #{{{ _writeRoster
    def _writeRoster(self):
        #write roster to file
        rF = open(self._rosterFile,'w')
        for item in self._roster.keys():
            name = str(item)
            priority = self._roster[item]['priority']
            show = self._roster[item]['show']
            if name and priority and show:
                try:
                    #TODO: figure out unicode stuff here
                    rF.write(name + "\n")
                except:
                    rF.write(name + "\n")

            else:
                rF.write(name + "\n")
                #rF.write("{{{ " + item + "\n" + item + "\n}}}\n")

        rF.close()
    #}}}

    #{{{ run
    def run(self):
        print "start"
        jid=xmpp.protocol.JID(self._jid)
        self.jabber =xmpp.Client(jid.getDomain(),debug=[])

        con=self.jabber.connect()
        if not con:
            sys.stderr.write('could not connect!\n')
            sys.exit(1)

        auth=self.jabber.auth(
            jid.getNode(),
            self._password,
            resource=jid.getResource())

        if not auth:
            sys.stderr.write('could not authenticate!\n')
            sys.exit(1)

        self.jabber.RegisterHandler('message',self.jabberMessageReceive)
        self.jabber.RegisterHandler('presence',self.jabberPresenceReceive)
        self.jabber.sendInitPresence(requestRoster=1)

        #Socket stuff
        RECV_BUF = 4096
        self.local = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.local.bind(('',2727))
        self.local.listen(1)
        self.xmppS = self.jabber.Connection._sock
        socketlist = [self.xmppS,self.local]
        online = 1

        while online:
            (i , o, e) = select.select(socketlist,[],[],1)
            for each in i:
                if each == self.xmppS:
                    self.jabber.Process(1)
                elif each == self.local:
                    sockfd, addr = self.local.accept()
                    socketlist.append(sockfd)
                else:
                    try:
                        data = each.recv(RECV_BUF)
                    except:
                        pass

                    if data:
                        try:
                            self.clientMessageProcess(data)
                        except Exception, e:
                            print e
    #}}}

    #From Jabber Functions
    #{{{ jabberMessageReceive
    def jabberMessageReceive(self, conn, msg):
        if msg.getBody():
            fromJid = str(msg.getFrom())
            body = str(msg.getBody())

            self._recievedMessage(fromJid, body)
    #}}}
    #{{{ jabberPresenceReceive
    def jabberPresenceReceive(self, conn, msg):
        jid = str(msg.getFrom())
        try:
            jid, resource = jid.split('/')
        except:
            resourc = ""

        try:
            oldPriority = self._roster[jid]['priority']
        except:
            oldPriority = None

        newPriority = msg.getPriority()
        self._roster[jid] = {'priority': newPriority,'show':msg.getShow()}
        self._writeRoster()
    #}}}

    #To Jabber Functions
    #{{{ jabberSendMessage
    def jabberSendMessage(self, tojid, msg):
        msg = msg.strip()
        m = xmpp.protocol.Message(to=tojid,body=msg,typ='chat')
        #print 'Message: ' + msg
        self.jabber.send(m)
    #}}}
    #{{{ jabberPresenceUpdate
    def jabberPresenceUpdate(self, show, status):
        m = xmpp.protocol.Presence(
            self._jid,
            show=show,
            status=status)
        self.jabber.send(m)
    #}}}
    #{{{ disconnect
    def disconnect(self):
        self.jabber.disconnect()
        self.local.close()
        self.destroy()
    #}}}

    #From Vim Functions
    #{{{ clientMessageProcess
    def clientMessageProcess(self, msg):
        #print msg
        msg = base64.b64decode(msg)
        msgParts = msg.split(':',1)
        command = msgParts[0]
        if command == "presenceUpdate":
            presenceParts = msgParts[1].split(':',1)
            show = presenceParts[0]
            status = presenceParts[1]
            self.jabberPresenceUpdate(show, status)
        elif command == "sendMessage":
            messageParts = msgParts[1].split(':',1)
            tojid = messageParts[0]
            message = messageParts[1]
            self.jabberSendMessage(tojid,message)
        elif command == "disconnect":
            self.disconnect()

    #}}}

    #To Vim Functions
    #{{{ toVim
    def toVim(self, cmd, silent=True):
        silent = "silent" if silent else ""
        toRun = self._vim + ' --servername %s -u NONE -U NONE --remote-send \
            \"<C-\\\\><C-N>:%s call %s<CR>"' % (
            self.vimServer, silent, cmd)
        os.system(toRun);
    #}}}

#}}}

#{{{ vimessengerSetupChatBuffer
def vimessengerSetupChatBuffer():
    commands = """\
    setlocal noswapfile
    setlocal buftype=nowrite
    setlocal noai
    setlocal nocin
    setlocal nosi
    setlocal syntax=dcl
    setlocal wrap
    map <buffer> <C-m>s :py sendMessage()<CR>
    """
    vim.command(commands)

    # This command has to be sent by itself.
    vim.command('au CursorMoved <buffer> sign unplace *')
#}}}
#{{{ vimessengerBeginChat
def vimessengerBeginChat():

    toJid = vim.current.line
    toJid = toJid.strip()


    user, domain = toJid.split('@')

    jid = toJid
    resource = ''
    if jid.find('/') >= 0:
        jid, resource = jid.split('/')

    chatKeys = chats.keys()
    chatFile = ''
    if toJid in chatKeys:
        chatFile = chats[toJid]
    else:
        chatFile = jid
        chats[toJid] = chatFile

    vim.command("bad " + chatFile)
    vim.command("e " + chatFile)

    vim.command("let b:buddyId = '" + toJid + "'")

    vimessengerSetupChatBuffer();

#}}}

#OUTGOING

#{{{ sendMessage
def sendMessage():
    import vim,base64

    try:
        toJid = vim.eval('b:buddyId')
    except:
        print "No chat found!"
        return 0

    origBuf = vim.current.buffer.name
    origBuf = origBuf.split('/')
    origBuf = origBuf[len(origBuf) - 1]

    chatKeys = chats.keys()
    chats[toJid]= origBuf

    r = vim.current.range
    body = ""
    for line in r:
        line = line.rstrip('\n')
        body = body + line + '\n'

    global chatServer
    chatServer.jabberSendMessage(toJid, body)

    msg = str(vim.current.line)
    vim.current.line = "Me: " + msg
#}}}
#{{{ signOff
def signOff():
    global chatServer
    chatServer.disconnect()
#}}}
#TODO: presenceUpdate()

#INCOMING (callbacks called from server)
#{{{ vimchatMessageReceived
def vimchatMessageReceived(fromJid, message):
    origBufNum = vim.current.buffer.number

    print "Message Recieved from: " + fromJid

    user, domain = fromJid.split('@')
    jid = fromJid
    resource = ''
    try:
        jid, resource = jid.split('/')
    except:
        resource = ""

    chatKeys = chats.keys()
    chatFile = ''
    if jid in chatKeys:
        chatFile = chats[jid]
    else:
        chatFile = jid
        chats[jid] = chatFile

    vim.command("bad " + chatFile)
    try:
        vim.command("sbuffer " + chatFile)
    except:
        vim.command("new " + chatFile)

    vim.command("let b:buddyId = '" + fromJid + "'")

    vimessengerSetupChatBuffer();

    messageLines = message.split("\n")
    toAppend = user + '/' + resource + ": " + messageLines[0]
    messageLines.pop(0)
    vim.current.buffer.append(toAppend)

    for line in messageLines:
        line = '\t' + line
        vim.current.buffer.append(line)

    vim.command("normal G")

    # Switch back to the original buffer.
    vim.command("sbuffer " + str(origBufNum))

#}}}

#{{{ vimessengerSignOn
def vimessengerSignOn():
    global chatServer
    global sendMessage

    jid = vim.eval('g:vimchat_jid')
    password = vim.eval('g:vimchat_password')

    chatServer = VimJabber(jid, password,vimchatMessageReceived)
    chatServer.start()
#}}}

EOF

" vim:et:fdm=marker:sts=4:sw=4:ts=4
